

#ifndef _C_GUI_H_
#define _C_GUI_H_




#include"gl_Graphics.h"
#include"gl_TextFont.h"
#include"stl_.h"

typedef struct __location__
{
	int left;
	int top;
}GUI_Location;

typedef struct __size__
{
	int height;
	int width;
}GUI_Size;

typedef struct __area__
{
	int left;
	int top;
	int right;
	int bottom;
}GUI_Area;

/// <summary>
/// 双向链表结点。参考linux内核的链表，只包含指针域，不包含数据域。
/// </summary>
typedef struct GUI_dlistNode__
{
	struct GUI_dlistNode__* prev;
	struct GUI_dlistNode__* next;
}GUI_dlistNode;

typedef struct _style__   
{
	int line_width;			//线宽
	COLOR_RGB line_color;  //线颜色（边框的线）
	COLOR_RGB back_color;  //背景色
}Style;

typedef struct _window__
{
	GUI_Location location;   // 窗口位置。
	Style style;             // 窗口背景样式。

	//控件消隐方式：用窗口的背景色重绘控件。
}Window;


/// <summary>
/// 使用位置和大小初始化区域。
/// </summary>
/// <param name="area">待初始化的区域结构体变量</param>
/// <param name="location">位置结构体</param>
/// <param name="size">尺寸的结构体</param>
void area_init(GUI_Area* area, GUI_Location* location, GUI_Size* size);

/// <summary>
/// 判断（x,y）坐标是否在区域area内。
/// </summary>
/// <param name="area">区域</param>
/// <param name="x">坐标x轴</param>
/// <param name="y">坐标y轴</param>
/// <returns>如果在区域内返回1，否则返回0。</returns>
bool is_enter_area(GUI_Area* area, int x, int y);


//标签最长的文本数量
#define Lable_Max_Text_Length  64 // 32

//按键，滑块，不包含文本。 
typedef struct _Label__
{
	GUI_Area area;   // area 和 location 可以决定size。 这个area是标签的显示范围。

	// 这里边框默认是1像素宽。UI设计要留出一像素宽度的区域。如果文本过长，就换行显示。 

	bool is_show_edge;  //是否显示边框。 默认显示。

	Style style;	   //边框样式

	/// <summary>
	/// 标签文本
	/// </summary>
	char text[Lable_Max_Text_Length];   
	/// <summary>
	/// 标签文本长度。
	/// </summary>
	int text_Length;       
	/// <summary>
	/// 文本的格式
	/// </summary>
	TextFont textfont;

	icon background_icon; // 背景图标
	GUI_Location background_location;  // 背景图标在画布中的位置。

}Lable;

typedef struct __Button__
{
	GUI_dlistNode       node;        //
	GUI_Area area;        // area 和 location 可以决定size。
	GUI_Location location;
	GUI_Size size;
	int r;             //圆角半径。按键都是圆角矩形。
	Lable* lable;      //跟随按键的标签

	bool is_selected;  // 是否选中。 触摸屏按下，接触到的第一个控件，即为选中的控件。如果要取消选中，则需要先松开触摸屏。
	bool is_hovor;		// 鼠标是否在控件内。 
	Style leave;	//按键离开
	Style hovor;	//按键进入
	void (*onClick)();  //按键回调函数，鼠标弹起时再响应。
}Button;

typedef struct __ScrollBar__  //滚动条
{
	GUI_dlistNode       node;          //
	GUI_Area area;      //滑块区域。
	GUI_Location location;
	GUI_Size size;

	//滑块就是一个可以移动的按键。area是滑块移动的区域。
	int thickness;  //滑块的厚度。必须小于 size的宽和高-线宽，否则放不下，thickness默认是 min(宽，高)/2 。  
	// 滚动条活动部分的圆头半径是 thickness/2，thickness最小是2，  |_____■_____________|
	int status;     //如果不设置，则根据滑块尺寸自动判断状态。0表示横，1表示竖。判断status会自动调整size，使得滑块至少有移动空间。

	int newMousePoint;
	int lastMousePoint; //记录鼠标的位置。如果status是0记录x坐标；如果status是1记录y坐标。

	int value;      //滑块的值，最小是0.
	int max_value;  //最大的值，根据滑块大小确定。 可以用来计算滑块的百分比。
	bool is_reverse;  // 是否反向。 默认正向，向左，向下是正向（xy坐标值增加的方向是正向）。  如果是反向，初始滑块在最大一端。  

	bool is_selected;  // 是否选中。 触摸屏按下，接触到的第一个控件，即为选中的控件。如果要取消选中，则需要先松开触摸屏。

	Lable* lable;       //跟随滑块的标签
	bool is_hovor;		// 鼠标是否在控件内。 

	COLOR_RGB slider_color;  // 圆头滑块的颜色。
	COLOR_RGB background_color;  // 圆头滑块的背景颜色。

	//滑块有四个状态：离开，悬浮，按下，弹起。四个状态有四个样式，其中弹起样式同悬浮。绘制函数分别绘制四个状态即可。
	Style leave;	//按键离开
	Style hovor;	//按键进入
	void (*onClick)();  //按键回调函数，鼠标弹起时再响应。
}ScrollBar;

typedef struct __ProgressBar__  //进度条
{
	GUI_Area area;      //滑块区域。
	GUI_Location location;
	GUI_Size size;

	//滑块就是一个可以移动的按键。area是滑块移动的区域。
	int thickness;  //滑块的厚度。必须小于 size的宽和高-线宽，否则放不下，thickness默认是 min(宽，高) 。  
	// 滚动条活动部分的圆头半径是 thickness/2，thickness最小是2，  |_____■_____________|
	int status;     //如果不设置，则根据滑块尺寸自动判断状态。0表示横，1表示竖。判断status会自动调整size，使得滑块至少有移动空间。

	int min_value;      //滑块的值，最小是0.
	int max_value;  //最大的值，根据滑块大小确定。 可以用来计算滑块的百分比。
	float percent; // 当前进度的百分比。

	bool is_reverse;  // 是否反向。 默认正向，向左，向下是正向（xy坐标值增加的方向是正向）。  如果是反向，初始滑块在最大一端，percent = (max_value - value)/max_value 。  

	COLOR_RGB slider_color;  // 圆头滑块的颜色。
	COLOR_RGB background_color;  // 圆头滑块的背景颜色。

	Style style;	//样式。只取其中的线宽和线颜色。
}ProgressBar;



//////////////////////////


/// <summary>
/// 初始化标签文本
/// </summary>
/// <param name="lable">标签指针</param>
/// <param name="left">标签位置x坐标</param>
/// <param name="top">标签位置y坐标</param>
/// <param name="w">标签宽度</param>
/// <param name="h">标签高度</param>
void lable_init(Lable* lable, int left, int top, int w, int h);
/// <summary>
/// 初始化标签文本
/// </summary>
/// <param name="lable">标签指针</param>
/// <param name="text">标签文本</param>
/// <param name="text_len">标签文本长度</param>
/// <param name="textfont">文本样式</param>
void lable_init_text(Lable* lable, const char* text, int text_len, TextFont textfont);
/// <summary>
/// 绘制标签
/// </summary>
/// <param name="lable">待绘制的标签</param>
void lable_draw(Lable* lable);

/// <summary>
/// 绘制标签边框
/// </summary>
/// <param name="lable">待绘制的标签</param>
void lable_draw_edge(Lable* lable);


/// <summary>
/// 按键初始化函数。样式使用默认样式。初始化后将控件插入链表。
/// </summary>
/// <param name="button">按键</param>
/// <param name="x">按键位置x坐标</param>
/// <param name="y">按键位置y坐标</param>
/// <param name="w">按键长</param>
/// <param name="h">按键宽</param>
void button_init(Button* button, int x, int y, int w, int h);
/// <summary>
/// 按键第一次绘制。
/// </summary>
/// <param name="button">按键</param>
void button_firstdraw(Button* button);

/// <summary>
/// 滚动条控件初始化。样式使用默认样式。初始化后将控件插入链表。
/// </summary>
/// <param name="scrollbar">滚动条控件</param>
/// <param name="x">滚动条位置x轴坐标</param>
/// <param name="y">滚动条位置y轴坐标</param>
/// <param name="w">滚动条位置宽</param>
/// <param name="h">滚动条位置高</param>
void scrollbar_init(ScrollBar* scrollbar, int x, int y, int w, int h);
/// <summary>
/// 滚动条第一次绘制
/// </summary>
/// <param name="scrollbar">滚动条</param>
void scrollbar_firstdraw(ScrollBar* scrollbar);


/// <summary>
/// 滚动条控件初始化。样式使用默认样式。初始化后将控件插入链表。
/// </summary>
/// <param name="progressbar">滚动条控件</param>
/// <param name="x">滚动条位置x轴坐标</param>
/// <param name="y">滚动条位置y轴坐标</param>
/// <param name="w">滚动条位置宽</param>
/// <param name="h">滚动条位置高</param>
void progressbar_init(ProgressBar* progressbar, int x, int y, int w, int h);
/// <summary>
/// 滚动条第一次绘制
/// </summary>
/// <param name="progressbar">滚动条</param>
void progressbar_firstdraw(ProgressBar* progressbar);


/// <summary>
/// 更新进度条百分比
/// </summary>
/// <param name="progressbar">进度条</param>
/// <param name="percent">新的百分比</param>
void progressbar_change(ProgressBar* progressbar, float percent);










/// <summary>
/// 初始化绘图设备，初始化GUI。
/// </summary>
void gui_init(void);



/*
	消息派遣的时候先遍历所有控件：
	如果控件is_finish == true，继续执行按键的响应函数。
	如果没有响应函数，再遍历一遍控件，进行消息派遣：
		如果鼠标在某个控件内，但is_hovor == false，说明鼠标进入了控件。is_hovor=true，绘制一次hovor的样式。停止遍历
		如果鼠标不在某个控件内，但is_hovor == true，说明鼠标离开了控件。is_hovor=false，绘制一次leave的样式。继续遍历
		如果鼠标在某个控件内，且is_hovor == true，说明鼠标停留在控件。将鼠标信息传递进响应函数，在响应函数里判断按键是否按下，控制is_finish的状态。然后继续遍历
		如果鼠标不在某个控件内，is_hovor == false，说明鼠标不在控件。继续遍历。
*/
/// <summary>
/// 将鼠标消息mouseMsg分发给各控件
/// </summary>
void dispatchMsg(int x, int y);



//初始化控件，绘制好后，实时跟新鼠标信息，调用dispatchMsg即可。 //下面就是怎么更新鼠标信息了。要同步所有信息。


void gui_test(void);




#endif
